package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.api.feign.ApArticleFeignClient;
import com.heima.audit.baidu.BaiduImageScan;
import com.heima.audit.baidu.BaiduTextScan;
import com.heima.audit.tess4j.Tess4jClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmAutoScanService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmAutoScanServiceImpl implements WmAutoScanService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private BaiduTextScan baiduTextScan;

    @Autowired
    private BaiduImageScan baiduImageScan;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private ApArticleFeignClient apArticleFeignClient;

    @Autowired
    private WmUserMapper wmUserMapper;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;
    
    @Autowired
    private Tess4jClient tess4jClient;
    /**
     * 审核自媒体文章
     *主方法
     * @param newsId 自媒体文章id
     */
    @Override
    @Async//使用异步线程
    @Transactional
    public void autoScanWmNews(Integer newsId) {
        //1.非空判断
        if(newsId==null){
            return;
        }
        //2.查询自媒体文章实体
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        if(wmNews==null){
            return;
        }
        
        //2.5 先抽取所有的文本和图片
        Map<String, Object> resultMap = handleTextAndImages(wmNews);


        //2.6 自管理敏感词的过滤
        Boolean sensitiveFlag = scanSensitiveText(wmNews, (String) resultMap.get("content"));
        if(!sensitiveFlag){
            return;
        }
        
        

        /**
         * 3.文本审核-百度云审核
         * status=1 合规
         * status=2 不合规
         * status=3 疑似
         * status=4 审核失败
         */
        Boolean textFlag = scanText(wmNews, (String) resultMap.get("content"));
        if(!textFlag){
            return;
        }

        //4.图片审核
        Boolean imageFlag = scanImage(wmNews, (List<String>) resultMap.get("imageList"));
        if(!imageFlag){
            return;
        }
        //5.审核通过，远程调用保存app端三剑客的接口
        ResponseResult result = saveArticleFromNews(wmNews);

        //6.修改wm_news状态=9
        if(result.getCode().equals(200)){
            wmNews.setArticleId(Long.valueOf(result.getData().toString()));
            updateWmNews(wmNews, (short) 9,"审核发布成功");
        }


    }

    /**
     * 抽取的第六个方法，自管理敏感词过滤
     * @param wmNews
     * @param content
     * @return
     */
    private Boolean scanSensitiveText(WmNews wmNews, String content) {
        Boolean flag=true;
        //1.查询敏感词的所有的敏感词
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(null);
        List<String> sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //2.执行初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //3.查找命中率
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if(map.size()>0){
            //有命中，代表了审核失败
            updateWmNews(wmNews, (short) 2,"文本内容中包含敏感词汇");
            flag=false;
        }
        return flag;
    }

    /**
     * 抽取的第五个方法，保存三剑客
     * @param wmNews
     */
    private ResponseResult saveArticleFromNews(WmNews wmNews) {
        ArticleDto dto=new ArticleDto();
        BeanUtils.copyProperties(wmNews,dto);
        //作者id和name
        dto.setAuthorId(wmNews.getUserId().longValue());
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        dto.setAuthorName(wmUser.getName());

        //频道id和name
        dto.setChannelId(wmNews.getChannelId());
        WmChannel wmChannel = wmChannelMapper.selectById(dto.getChannelId());
        dto.setChannelName(wmChannel.getName());

        //布局
        dto.setLayout(wmNews.getType());

        //创建时间
        dto.setCreatedTime(new Date());

        //设置行为数量默认为0
        dto.setViews(0);
        dto.setLikes(0);
        dto.setComment(0);
        dto.setCollection(0);

        ResponseResult result = apArticleFeignClient.save(dto);
        return  result;
    }

    /**
     * 抽取的第四个方法，审核图片
     * @param wmNews
     * @param imageList 图片地址集合
     * @return
     */
    private Boolean scanImage(WmNews wmNews, List<String> imageList) {
        //初始化标识，true表示通过，false表示审核失败
        Boolean flag=true;

        if(imageList!=null && imageList.size()>0){

            //对图片进行去重操作
            imageList = imageList.stream().distinct().collect(Collectors.toList());

            for (String path : imageList) {
                //下载图片
                byte[] bytes = fileStorageService.downLoadFile(path);
                
        //调用OCR技术实现过滤
                ByteArrayInputStream input=new ByteArrayInputStream(bytes);
                BufferedImage bufferedImage= null;
                try {
                    bufferedImage = ImageIO.read(input);
                    String resultText = tess4jClient.doOCR(bufferedImage);
                    //调用自管理敏感词的过滤
                    flag = this.scanSensitiveText(wmNews, resultText);
                    if(!flag){
                        return false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }

                
                
                //调用百度云审核的接口
                Integer status = baiduImageScan.imageScan(bytes);
                if(status==2){
                    //修改wm_news表
                    updateWmNews(wmNews, (short) 2, "图片中可能包含不合规的内容");
                    flag=false;
                    break;
                }else if(status==3){
                    //修改wm_news表
                    updateWmNews(wmNews, (short) 3, "图片中可能包含疑似不合规的内容,请通过人工审核");
                    flag=false;
                    break;
                }else if(status==4){
                    //修改wm_news表
                    updateWmNews(wmNews, (short) 2, "图片中可能包含审核失败的内容");
                    flag=false;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * 抽取的第三个方法，审核文本内容
     * @param wmNews
     * @param content
     * @return
     */
    private Boolean scanText(WmNews wmNews, String content) {
        //初始化标识，true表示通过，false表示审核失败
        Boolean flag=true;
        //调用审核的接口
        Integer status = baiduTextScan.textScan(content);

        if(status==2){
            //修改wm_news表
            updateWmNews(wmNews, (short) 2, "内容中可能包含不合规的词汇");
            flag=false;
        }else if(status==3){
            //修改wm_news表
            updateWmNews(wmNews, (short) 3, "内容中可能包含疑似不合规的词汇,请通过人工审核");
            flag=false;
        }else if(status==4){
            //修改wm_news表
            updateWmNews(wmNews, (short) 2, "内容中可能包含审核失败的词汇");
            flag=false;
        }
        return flag;
    }

    /**
     * 抽取的方法，修改wm_news表
     * @param wmNews
     * @param status
     * @param message
     */
    private void updateWmNews(WmNews wmNews, short status, String message) {
        wmNews.setStatus(status);
        wmNews.setReason(message);
        wmNewsMapper.updateById(wmNews);
    }

    /**
     * 抽取的第一个方法，先抽取所有的文本和图片
     * @param wmNews
     * @return
     */
    private Map<String,Object> handleTextAndImages(WmNews wmNews) {
        //定义字符串和集合用来封装文章内容和图片
        StringBuilder sb=new StringBuilder();
        List<String > imageList=new ArrayList<>();

        String title= wmNews.getTitle();
        sb.append(title);

        String content = wmNews.getContent();
        List<Map> contentList = JSONArray.parseArray(content, Map.class);
        for (Map map : contentList) {
            //获取图片
            if(map.get("type").equals("image")){
                imageList.add((String) map.get("value"));
            }
            //获取内容
            if(map.get("type").equals("text")){
                sb.append((String) map.get("value"));
            }
        }
        //封装封面图片到imageList中
        String images = wmNews.getImages();
        if(images!=null){
            imageList.addAll(Arrays.asList(images.split(",")));
        }


        //封装数据
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("content",sb.toString());
        resultMap.put("imageList",imageList);
        return resultMap;
    }
}
